package com.lzyyj.common;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Cglib方式实现的对象包装器
 * @author Lzyyj
 */
public class CglibWrapper implements MethodInterceptor {

	private static final Log log = LogFactory.getLog(CglibWrapper.class);

	/**
	 * 属性关系映射表
	 */
	private Map<String, String> propertyRelation = new HashMap<String, String>();
	
	/**
	 * 被包装的源对象
	 */
	private Object source;

	private CglibWrapper(Object source) {
		this.source = source;
	}

	public CglibWrapper(Map<String, String> propertyRelation, Object source) {
		this.propertyRelation = propertyRelation;
		this.source = source;
	}

	@SuppressWarnings("unchecked")
	public static <T> T wrap(Class<T> clazz, Object source) {
		Enhancer en = new Enhancer();
		en.setSuperclass(clazz);
		en.setCallback(new CglibWrapper(source));
		T tt = (T) en.create();
		return tt;
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		Object result = null;

		log.debug("拦截前...");

		String propertyName = null;
		String ms = null;
		String methodName = method.getName();
		if (methodName.startsWith("is")&&args==null&&methodName.length()>2){
			// is开头，无参，返回类型为 boolea
			propertyName = methodName.substring(2,3).toLowerCase()+methodName.substring(3);
			ms = "is";
		}else if (methodName.startsWith("get")&&methodName.length()>3&&(args==null||args.length==0)){
			// 无参，
			propertyName = methodName.substring(3,4).toLowerCase()+methodName.substring(4);
			ms = "get";
		}else if (methodName.startsWith("set")&&args.length==1&&methodName.length()>3){
			propertyName = methodName.substring(3,4).toLowerCase()+methodName.substring(4);
			ms = "set";
		}else{
			// 非属性封装，应该是一般的方法，先照搬，不做特殊处理
		}
		
		Method m ;
		if (propertyName!=null){
			// 属性操作方法
			if (propertyRelation.containsKey(propertyName)){
				// 获取映射属性名
				String sourceProperty = propertyRelation.get(propertyName);
				String newMethodName = ms + sourceProperty.substring(0, 1).toUpperCase()+ sourceProperty.substring(1);
				m = source.getClass().getMethod(newMethodName, method.getParameterTypes());
			}else{
				m = source.getClass().getMethod(methodName, method.getParameterTypes());
			}
			
		}else{
			// 非属性操作方法
			m = source.getClass().getMethod(methodName, method.getParameterTypes());
		}
		
		if (m!=null){
			result = m.invoke(source, args);
		}

		log.debug("拦截后....");

		return result;

	}

}
